# 冒号前是键，后是值（键和值都是唯一的，重复写入则后键覆盖前键，键和值合称项）
dict1 = {"name": "yangshuo", "age": 18}
# 利用dict将列表转化成字典，但列表内元组必须是二元组
dict2 = dict([("name", "ys"), ("age", 18)])
# 使用变量名作为键，变量作为值创建字典
dict3 = dict(name="ys", age=18, city="shaoyang")

# 新增和修改（创建相同键修改值就可以覆盖原键了），键不能修改，只能修改值
# 字典中存在键就是修改，不存在键就是新增
dict1["city"] = "shaoyang"
dict1["age"] = "eighteen"
print(dict1)

# setdefault函数也类似于添加键值对(不能做修改),先键后值
dict1.setdefault("computer", "ASUS")
print(dict1)

# 字典合并
a = {"telephone": 13873952037}
dict1.update(a)  # 两个字典合并只能用update函数，因为字典不支持用+号连接
print(dict1)

dict1.clear()  # clear函数用于删除字典里面所有的值
print(dict1)

# 在调用clear()方法后，字典dict1会变为空字典，
# 因此后续调用pop("age")会引发KeyError，因为字典中不存在"age"键
dict2.pop("age")  # pop函数可以删除指定项(根据key进行删除)，删除的是键值对，返回值是key对应的value
dict2.popitem()  # popitem()的返回值是(key,value),默认从后往前删
# del dict2["name"]       # del关键字也可以直接删除字典
print(dict2)

# 创建一个含两本书籍信息的元组型列表，删除书籍的出版社信息再打印出来
list = [
    {"书名": "《三体》", "作者": "刘慈欣", "价格": 20, "出版社": "***出版社"},
    {"书名": "《流浪地球》", "作者": "刘慈欣", "价格": 18, "出版社": "###出版社"}
]
for book in list:
    book.pop("出版社")
print(list)

# 字典中的查询
if "city" in dict3:
    print(dict3["city"])
len(dict3)  # 表示字典dict3中有几对键值对

# 使用fromkeys函数创建新字典，可后来对键进行新增赋值
new_dict = dict.fromkeys(["name", "age"])
new_dict["name"] = "zyl"
print(new_dict)

# 使用get函数也可以查找键的值
print(new_dict["name"])  # 找不到会报错
print(new_dict.get("name"))  # 找不到会返回None,后还可设默认值（找不到就找默认值，如new_dict.get("name_1,"zyl"))

# 字典的遍历
# 如果直接使用for···in···的方式进行遍历，取出的是字典的键而非值
for k, v in new_dict.items():  # item函数将所有项放在一个列表中，按键值对的方式用元组存放
    print(f"key={k},value={v}")

for k in new_dict.keys():  # key函数查询键
    print(k)
for v in new_dict.values():  # values函数查询值
    print(v)

# set集合中的元素不可重复且无序，相当于只有键没有值的字典
# 创建集合使用{}或者set()，但是创建空集合只能是set(),因为{}是创建空字典
# 集合和字典没有下标，只有序列才有下标
set1 = set()  # 创建空集合
set2 = {"abcdefg", 100, 78, 3.14}
print(len(set2))  # 查询集合长度

# 添加集合元素,添加顺序是基于哈希算法，可以理解为无序
set2.add(99)
set2.add("hello")
print(set2)

# 集合特征：{元素,元素,元素······} ----> 集合

# 删除元素
set2.remove(99)  # 若删除元素不在集合中则报错
print(set2)
set2.discard(99)  # 若删除元素不在集合中则不做出任何反应
set2.pop()  # 随机删除集合中的元素
del set2  # 关键词del只能删除集合，无法删除某个具体的元素

# set集合是唯一的，其中不能放列表（列表属于可变类型）
# 不可变类型：基本类型（字符串，int，float等），tuple[往往是python内置类型]
# 可变类型：list,dict,set

# 不可变类型内存地址查询
s1 = "hello"
print(id(s1))
s1 = "abcdefg"
print(id(s1))  # s1修改前后内存地址不一致，属于不可变类型

# 可变类型内存地址查询
print("-" * 50)
lst = [100, 200, 300]
print(id(lst))
lst.append(400)
lst.insert(0, 0)
print(id(lst))  # lst修改前后内存地址一致，属于可变类型

# 删去一个列表中的重复数据
list_1 = [1, 5, 6, 8, 1, 5, 6, 9, 4, 7]
set3 = set(list_1)  # 利用集合的不可重复性删除
print(set3)

# 生成5组（不允许重复），字母和数字组成4位验证码
import random

code_list = set()
y = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890"
while True:
    code = ''
    for i in range(4):
        r = random.choice(y)  # 可以通过choice函数直接调用变量y中的数据
        code += r
    # 将code添加到set中
    code_list.add(code)
    # 判断长度
    if len(code_list) == 5:
        break
print(code_list)

# 集合：交集 intersection   并集 union    差集（补集） difference
set4 = {1, 2, 3, 4, 5}
set5 = {4, 5, 6, 7, 8}
result = set4.intersection(set5)  # 返回值为两个集合的交集
result_1 = set4.union(set5)  # 返回值为两个集合的并集
result_2 = set4.difference(set5)  # 返回值为set4中与set5相异的差集部分

answer = chr(65)  # 给ASCII码值，返回对应的字母
print(answer)
answer_1 = ord("A")  # 给字母，返回对应的ASCII码值
print(answer_1)

# 集合推导式(类似列表推导式，在基础上加上了去重操作)
list_2 = [1, 2, 1, 3, 5, 2, 1]
set6 = {x + 1 for x in list_2}
print(set6)

# 字典推导式
dict4 = {"a": "A", "b": "B", "c": "C", "d": "C"}
newdict = {value: key for key, value in dict4.items()}
print(newdict)